package com.example.bean.lifecycle;

import org.junit.Assert;
import org.junit.Test;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.*;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author linfeng
 * @date 2022/4/14 15:17
 */
public class InstantiationAwareBeanPostProcessorTestOne {

    public static class SimpleInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor{

        // 一旦这个方法返回一个非空的对象，那么该bean的相关初始化回调（比如各种Aware接口）、属性注入 都不会被执行，
        // 唯一应用的进一步处理是来自配置的BeanPostProcessors的postProcessAfterInitialization回调。
        @Override
        public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
            if(beanClass == SimpleTestBean.class){
                System.out.println("通过postProcessBeforeInstantiation()返回一个新的simpleTestBean");
                SimpleTestBean simpleTestBean = new SimpleTestBean("张三");
                return simpleTestBean;
            }
            return null;
        }

        @Override
        public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
            // 由于SimpleInstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation()方法返回了一个非空的实例，
            // 本方法将不会被执行

            System.out.println("SimpleInstantiationAwareBeanPostProcessor#postProcessAfterInstantiation()方法被执行");
            return true;
        }
    }

    public static class SimpleTestBean implements BeanNameAware, BeanFactoryAware, ApplicationContextAware, BeanClassLoaderAware, InitializingBean {
        private String name;

        private String beanName;
        private BeanFactory beanFactory;
        private ApplicationContext applicationContext;
        private ClassLoader beanClassLoader;

        public SimpleTestBean() {
            System.out.println("SimpleTestBean无参构造方法被调用");
        }

        public SimpleTestBean(String name) {
            this.name = name;
            System.out.println("SimpleTestBean带参构造方法被调用，参数：" + name);
        }

        @Override
        public void setBeanClassLoader(ClassLoader classLoader) {
            // 由于SimpleInstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation()方法返回了一个非空的实例，
            // 本方法将不会被执行

            System.out.println("SimpleTestBean#setBeanClassLoader()方法被执行");

            this.beanClassLoader = classLoader;
        }

        @Override
        public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
            // 由于SimpleInstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation()方法返回了一个非空的实例，
            // 本方法将不会被执行

            System.out.println("SimpleTestBean#setBeanFactory()方法被执行");

            this.beanFactory = beanFactory;
        }

        @Override
        public void setBeanName(String name) {
            // 由于SimpleInstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation()方法返回了一个非空的实例，
            // 本方法将不会被执行

            System.out.println("SimpleTestBean#setBeanName()方法被执行");

            this.beanName = name;
        }

        @Override
        public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
            // 由于SimpleInstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation()方法返回了一个非空的实例，
            // 本方法将不会被执行

            System.out.println("SimpleTestBean#setApplicationContext()方法被执行");

            this.applicationContext = applicationContext;
        }

        @Override
        public void afterPropertiesSet() throws Exception {
            // 由于SimpleInstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation()方法返回了一个非空的实例，
            // 本方法将不会被执行
            System.out.println("SimpleTestBean#afterPropertiesSet()方法被调用");
        }

        // setter and getter

        public void setName(String name) {
            this.name = name;
        }

        public String getName() {
            return name;
        }

        public String getBeanName() {
            return beanName;
        }

        public BeanFactory getBeanFactory() {
            return beanFactory;
        }

        public ApplicationContext getApplicationContext() {
            return applicationContext;
        }

        public ClassLoader getBeanClassLoader() {
            return beanClassLoader;
        }
    }

    @Configuration
    public static class AppConfig {

        @Bean
        public SimpleTestBean simpleTestBean(){
            // 由于SimpleInstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation()方法返回了一个非空的实例，
            // 所以这里的代码将不会被执行
            SimpleTestBean simpleTestBean = new SimpleTestBean();
            simpleTestBean.setName("李四");
            return simpleTestBean;
        }

        @Bean
        public SimpleInstantiationAwareBeanPostProcessor simpleInstantiationAwareBeanPostProcessor(){
            return new SimpleInstantiationAwareBeanPostProcessor();
        }
    }

    @Test
    public void test(){
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        SimpleTestBean bean = context.getBean(SimpleTestBean.class);

        Assert.assertEquals("张三", bean.getName());

        Assert.assertNull(bean.getBeanName());
        Assert.assertNull(bean.getBeanFactory());
        Assert.assertNull(bean.getBeanClassLoader());
        Assert.assertNull(bean.getApplicationContext());
    }
}
